﻿using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

namespace Nemerle.Contrib
{
    public macro @with (obj, assignmentExprs) 
    {
        WithImpl.WithImpl(obj, assignmentExprs)
    }
    
    module WithImpl
    {
        public WithImpl(obj : PExpr, assignmentExprs : PExpr) : PExpr
        {
            def exprs = match (assignmentExprs) {
                | PExpr.Sequence(elements) => elements;
                | _ => Message.FatalError("'with' must be given a Sequence of assignment statements.");
            };
            
            def createTemp = <[ def temp = $obj ]>;
            def assignments(xs) {
                | <[ $(name : name) = $value ]> :: xs => <[ temp.$(name : name) = $value ]> :: assignments(xs);
                | [] => [ <[ temp ]> ];
                | _ => Message.FatalError("'with' must be given a Sequence of assignment statements.");
            };
            <[ { .. $( createTemp :: assignments(exprs) ) } ]>
        }
    }
}
